По умолчанию система не уведомляет службы о событиях управления питанием. Система осуществляет переходы между различными режимами энергопотребления, не требуя никаких действий со стороны служб.
Если Ваша служба должна участвовать в принятии решений об управлении питанием:
Выполните следующие действия, чтобы получать уведомления о событиях управления питанием:
Служба должна сообщить системе, что она будет принимать и обрабатывать сообщения об управлении питанием следующим образом: При вызове службой функции SetServiceStatus должен устанавливаться бит SERVICE_ACCEPT_POWEREVENT в поле dwControlsAccepted структуры SERVICE_STATUS.
Управляющая функция-обработчик службы должна быть функцией «HandlerEx», как описано в документе по адресу
http://msdn.microsoft.com/library/sdkdoc/winbase/services_3smw.htm
Службы должны использовать функцию RegisterServiceCtrlHandlerEx для регистрации управляющей функции-обработчика «HandlerEx». Управляющие функции-обработчики «HandlerEx» поддерживают новые управляющие коды события управления питанием (в то время как управляющие функции-обработчики типа «Handler» не поддерживают).
После того включения уведомлений о событиях управления питанием Вашей службы она должна будет отвечать на управляющие запросы SERVICE_CONTROL_POWEREVENT и обрабатывать их точно так же, как и сообщения WM_POWERBROADCAST, перечисленные ранее в этой главе и необходимые для соответствия требованиям OnNow/ACPI. Получение сообщения SERVICE_CONTROL_POWEREVENT эквивалентно получению сообщения WM_POWERBROADCAST.
Сравнение уведомлений об управлении питанием
| Первая ячейка | Вторая ячейка | |
| Не службы | Службы | |
| Событие управления питанием | WM_POWERBROADCAST | SERVICE_CONTROL_POWEREVENT |
| Параметр события | wParam | dwEventType |
| Параметр события | lParam | lpEventData |
| Если запрос принят | Вернуть TRUE | Вернуть NO_ERROR |
| Если запрос отклонен | Вернуть BROADCAST_QUERY_DENY | Вернуть любой код ошибки |
Пример OnNow:
В приведенном ниже примере показана обработка сообщений об управлении питанием в процедуре wndproc.
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// НАЗНАЧЕНИЕ: Обработка сообщений, приходящих главному окну.
//
// WM_COMMAND - обработка меню приложения
// WM_PAINT - рисование главного окна
// WM_DESTROY - отправка сообщения о выходе и возврат
//
//
BOOL g_bAvoidIO = FALSE;
TCHAR g_szTitle[] = _T("Ждущий режим");
TCHAR g_szText[] = _T("Получен запрос о переходе в ждущий режим. ")
_T("Закрыть все файлы и соединения?");
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
SYSTEM_POWER_STATUS Status;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Разбор выбора из меню
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd,
(DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_POWERBROADCAST:
switch(wParam)
{
case PBT_APMBATTERYLOW:
// Аккумулятор разряжен. Используется для определения,
// нужно ли отменить любой ввод/вывод или можно
// использовать столько энергии, сколько необходимо.
g_bAvoidIO = TRUE;
break;
case PBT_APMOEMEVENT:
// Специфические события OEM
break;
case PBT_APMPOWERSTATUSCHANGE:
// Компьютер был помещен или изъят из стационарного устройства, срок работы
// аккумулятора менее 5 минут, осталось 10% мощности аккумулятора, энергия
// аккумулятора изменилась на 3% и т.д. Нас интересует только, подключен ли
// компьютер к сети. При питании от аккумулятора необходимо экономно
// расходовать энергию.
// Здесь можно производить и другие действия, например, если
// выполняется операция, которая продлится дольше, чем
// остается времени (мощности) работы аккумулятора,
// Вы можете остановить процесс и проинформировать пользователя о том,
// что времени для завершения текущей операции
// недостаточно.
GetSystemPowerStatus(&Status);
g_bAvoidIO = Status.ACLineStatus == 1 ? FALSE : TRUE;
break;
case PBT_APMQUERYSUSPEND:
// Если потери или повреждения данных не произошло, всегда возвращать
// TRUE. Если данные могли быть потеряны или повреждены,
// проверяйте старший бит значения lParam перед отображением любого
// элемента интерфейса пользователя.
// Если пользователь не ответит за разумное
// время, система перейдет в ждущий режим, так что НЕ ДЕЛАЙТЕ ТАК
// без крайней необходимости.
if (g_bNetDataDirty )
{
if(lParam & 0x00000001)
{
if (IDNO == MessageBox(hWnd, g_szText, g_szTitle,
MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL))
return BROADCAST_QUERY_DENY;
else
// Пользователь требует перехода в спящий режим
// с потерей сетевых данных.
return TRUE;
}
else
return BROADCAST_QUERY_DENY;
}
else
return TRUE;
case PBT_APMQUERYSUSPENDFAILED:
// В обработчике PBT_APMQUERYSUSPEND мы ничего не делаем, так что
// нет необходимости делать что-либо здесь. Если бы в уведомлении
// PBT_APMQUERYSUSPEND что-то происходило, здесь
// надо было бы отменять эти действия.
break;
case PBT_APMRESUMEAUTOMATIC:
// Это уведомление необходимо обрабатывать, если бы мы обрабатывали
// восстановление при поступлении запроса из сети,
// от модема и т.д. Мы НЕ хотим обрабатывать
// эту ситуацию, так же как и событие PBT_APMRESUMESUSPEND
// потому что в этот момент нет взаимодействия с пользователем. Как
// только система Windows обнаружит вмешательство пользователя
// (передвижение мыши, нажатие клавиши и т.д.), система
// сообщит об этом с помощью уведомления PBT_RESUMESUSPEND.
break;
case PBT_APMRESUMECRITICAL:
// Данное уведомление означает, что система перешла в ждущий режим,
// не отправив приложениям соответствующие сообщения. Приложение
// должно восстановить сетевые соединения,
// повторно открыть все файлы и восстановить общее
// состояние приложения. Также необходимо попытаться определить
// возможную потерю или повреждение данных и уведомить пользователя.
break;
case PBT_APMRESUMESUSPEND:
// Восстановить все сетевые соединения, сохраненные в функции suspend
// и/или повторно открыть все файлы и переместить указатели
// текущего положения на сохраненные позиции.
// Если файлы находятся на локальном диске, их состояние будет
// сохранено; Вам нужно будет отслеживать, какие файлы находятся
// на локальных дисках, а какие на сетевых
// устройствах.
Resume();
break;
case PBT_APMSUSPEND:
// Сохраните необходимую информацию для восстановления сетевых
// соединений и/или закройте все файлы и сохраните информацию,
// необходимую для восстановления состояния каждого файла (имя
// файла/путь, позиция указателя в файле и т.д.).
Suspend();
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}